from rich.panel import Panel
import re
from rich.box import HEAVY_EDGE
from rich.syntax import Syntax
from termdb.utils.charts.base import Base
import pygetwindow as gw
import platform


class Input(Base):
    HIGH_LIGHT_WORDS_BLUE = ["into", "select", "update", "insert", "delete", "from", "where", "order", "by", "limit",
                             "having", "join", "left", "right", "inner", "outer", "union", "group",
                             "intersect", "except", "on", "and", "or", "not",
                             "like", "in", "between", "case", "when", "then", "else", "end", "null", "true", "false",
                             "exists", "distinct", "count", "sum", "avg", "max", "min", "round", "floor", "ceil",
                             "truncate", "trunc", "show"]

    def __init__(self, **kwargs):
        self.texts = []
        self.text = ""
        self.input_cursor = 0
        self.line_cursor = 0
        self.hotkey_bind_functions = {
            "<cmd>+<backspace>": self.cmd_backspace,
            "<ctrl>+<backspace>": self.cmd_backspace,
            "<cmd>+<down>": self.cmd_down,
            "<ctrl>+c": self.exit
        }
        self.key_bind_functions = {
            "<left>": self.left,
            "<right>": self.right,
            "<backspace>": self.backspace,
            "<up>": self.up,
            "<down>": self.down,
            "<delete>": self.delete,
            "<enter>": self.enter,
            "<esc>": self.esc
        }
        self.input_bind_functions = self.input
        self.panel_args = kwargs
        self.mode = "input"
        self.choice_line_range = []
        self.start_line = 0
        self.parse_mode = False
        if platform.system() == "Windows":
            self.line_split = "\r"
        else:
            self.line_split = "\n"

    def __rich_console__(self, console, options):
        self.width = options.max_width or console.width
        self.height = options.height or console.height

        yield Panel(self.get_text(), expand=True, width=self.width, padding=(0, 2),
                    box=HEAVY_EDGE, **self.panel_args,
                    title=f"char:{len(self.text)}/input_cursor:{self.input_cursor}/line-cursor:{self.line_cursor}"
                          f"/height:{self.height}/lines:{self._count_lines()}/start_line:{self.start_line}",
                    subtitle=self.text)

    def input(self, keyword: str):
        # 输入处理逻辑
        allowed_pattern = (r'^[\u4e00-\u9fa5A-Za-z0-9\w'
                           r'.,，。；：“”‘’【】「」（）¥……！《》、——｜～;!?()\'"\-\|_/\*=:<>\{\}\[\]\$#%@!&\*\^+`;\\\n\r ]+$')
        if self.mode == "view":
            return self._command(keyword)

        if re.match(allowed_pattern, keyword):
            if keyword == self.line_split:
                if self.line_cursor >= self.height - 2:
                    self.start_line += 1
                self.line_cursor += 1
                self.texts.append(self.text)
                self.text = ""

            else:
                self.text += keyword
            self.input_cursor += 1
            return True

        return False

    def _command(self, keyword: str):
        # 命令处理逻辑
        if keyword == "":
            return
        if keyword == "d":
            self.texts.pop(self.line_cursor - 1)
            if self._count_lines() <= self.line_cursor:
                self.line_cursor -= 1
            self.choice_line_range = [self.line_cursor]

        elif keyword == "w":
            if self.line_cursor > 0 and self.line_cursor - 1 in self.choice_line_range:
                self.line_cursor -= 1
                self.choice_line_range.pop(-1)

        elif keyword == "s":
            if self.line_cursor <= self._count_lines():
                if self.line_cursor not in self.choice_line_range:
                    self.choice_line_range.append(self.line_cursor)
                self.line_cursor += 1

        elif keyword == ":":
            pass

    def esc(self):
        if self.mode == "view":
            self.mode = "input"
        else:
            self.mode = "view"

    def up(self):
        if self.current_window_name != gw.getActiveWindow():
            return
        if self.line_cursor > 1:
            self.line_cursor -= 1
        self.input_cursor = len(
            self.line_split.join(self.texts[:self.line_cursor]))
        self.choice_line_range = [self.line_cursor]
        if self.start_line > 0:
            self.start_line -= 1

    def down(self):
        if self.current_window_name != gw.getActiveWindow():
            return
        if self.line_cursor <= self._count_lines():
            self.input_cursor = len(
                self.line_split.join(self.texts[:self.line_cursor]))
            self.line_cursor += 1
        self.choice_line_range = [self.line_cursor]
        if self.line_cursor + 1 > self.height:
            self.start_line += 1

    def _get_not_visible_texts(self):
        if self._count_lines() > self.height:
            return self.texts[:self.start_line]
        return ""

    def _len_not_visible_text(self):
        return len(self.line_split.join(self._get_not_visible_texts()))

    def backspace(self):
        if self.current_window_name != gw.getActiveWindow():
            return
        if self.mode != "input":
            return
        if self.input_cursor > 0:
            self.texts[self.line_cursor] = (self.texts[self.line_cursor][:self.input_cursor - 1] +
                                            self.texts[self.line_cursor][self.input_cursor:])
            self.input_cursor -= 1
            return True
        elif self.text == "":
            self.text = " "

        return False

    def delete(self):
        if self.current_window_name != gw.getActiveWindow():
            return
        if self.mode != "input":
            return
        if self.input_cursor < len(self.text):
            self.texts[self.line_cursor] = (self.texts[self.line_cursor][:self.input_cursor] +
                                            self.texts[self.line_cursor][self.input_cursor+1:])
            self.input_cursor -= 1

            return True

    def enter(self):
        if self.current_window_name != gw.getActiveWindow():
            return

    def cmd_backspace(self):
        if self.current_window_name != gw.getActiveWindow():
            return
        if self.mode != "input":
            return
        self.texts = []
        self.text = ""
        self.input_cursor = 1
        self.line_cursor = 1
        self.start_line = 0

        return True

    def cmd_down(self):
        self.choice_line_range.append(self.line_cursor)
        self.line_cursor += 1

        return True

    def left(self):
        if self.current_window_name != gw.getActiveWindow():
            return
        if self.mode != "input":
            return
        if self.line_cursor > 0 and self.input_cursor > 0:

            if self.texts[self.line_cursor][self.input_cursor-2] == self.line_split:
                self.input_cursor -= 1
                self.line_cursor -= 1
            self.input_cursor -= 1

            return True
        return False

    def right(self):
        if self.current_window_name != gw.getActiveWindow():
            return
        if self.mode != "input":
            return
        if self.input_cursor < len(self.text):

            if self.text[self.input_cursor] == self.line_split:
                self.input_cursor += 1
                self.line_cursor += 1
            self.input_cursor += 1

        elif self.input_cursor == len(self.text) and not self.text.endswith(" "):
            self.text += " "
            self.input_cursor += 1
        return True

    def _count_lines(self):
        # 计算文本行数
        return len(self.texts)

    def _get_visible_text(self):
        # 获取可见文本
        end_line = self.start_line + self.height
        return self.line_split.join(self.text.split(self.line_split)[self.start_line:end_line])

    def get_text(self):
        if self.input_cursor == 0:
            self.input_cursor = 1

        if self.input_cursor > len(self.text):
            self.input_cursor = len(self.text)
        if not self.text:
            self.text = " "
            self.input_cursor = 1

        visible_text = self._get_visible_text()

        syntax = Syntax(visible_text, "sql", theme="monokai", word_wrap=True, line_numbers=True,
                        highlight_lines=set(self.choice_line_range), start_line=self.start_line + 1)
        highlighted_text = syntax.highlight(visible_text)
        highlighted_text.stylize("bold u",
                                 self.input_cursor - (len(self.text) - len(self._get_visible_text())) - 1,
                                 self.input_cursor - (len(self.text) - len(self._get_visible_text())))
        if self.mode == "input":
            return highlighted_text
        else:
            return syntax


if __name__ == '__main__':
    from rich.live import Live

    i = Input()
    sql = """SHOW CREATE TABLE "keta-dbtest-oceanbase_phoenix".`ace_tags_enrichment_schema`;"""

    with Live(i) as live:
        # i.loop()
        pass
